Skip to content

fix(db): centralize DB_AHEAD marker as shared const (Sourcery on PR #64)#65

Merged
thierryvm merged 1 commit into
mainfrom
hotfix/v0.3.10-db-ahead-marker-robust
May 11, 2026
Merged

fix(db): centralize DB_AHEAD marker as shared const (Sourcery on PR #64)#65
thierryvm merged 1 commit into
mainfrom
hotfix/v0.3.10-db-ahead-marker-robust

Conversation

@thierryvm

@thierryvm thierryvm commented May 11, 2026

Copy link
Copy Markdown
Owner

Sourcery feedback on the freshly-merged PR #64

Le mécanisme de signalement DB_AHEAD repose sur la correspondance exacte de préfixes de chaîne (par ex. Failed to init SQLite: DB_AHEAD::...) ; il serait préférable de centraliser ce marqueur dans une constante partagée ou d'utiliser un type d'erreur structuré, afin que de futures refactorisations ne cassent pas accidentellement la logique de strip_prefix dans lib.rs.

Fix

  • New pub const db::DB_AHEAD_MARKER = "DB_AHEAD::" — single source of truth.
  • init_pool (producer) uses the constant via interpolation.
  • lib.rs::setup (consumer) uses e.find(db::DB_AHEAD_MARKER) instead of strip_prefix("Failed to init SQLite: DB_AHEAD::"). Robust to any future change in upstream wrapping — only the marker itself needs to stay stable, and that's now a single named symbol the compiler tracks.
  • Cleaned the lib.rs comment to make the path semantics explicit: STARTUP_BLOCKED.txt lives in dirs::data_dir().join("getpostcraft") next to app.db, NOT in the log dir which Tauri puts under the bundle identifier (app.getpostcraft) on Windows.

Tests

+1 regression guard db_ahead_marker_is_findable_even_when_wrapped exercises 4 distinct wrappings:

  1. "Failed to init SQLite: {marker}payload" (current production wrap)
  2. "Some new wrapping: {marker}payload" (any future refactor)
  3. "{marker}payload" (no wrap at all)
  4. "Layer A → Layer B: {marker}payload" (multi-layer wrap)

Asserts the payload is extracted cleanly in every case. The 3 existing tests (db_ahead_check_passes_on_fresh_install, db_ahead_check_passes_when_db_matches_binary, db_ahead_check_blocks_when_db_has_future_migration) continue to validate the functional pre-flight check.

Rust 205/205 (was 204/204), clippy + fmt clean.

After merge

Tag v0.3.10 → workflow Release builds the 3-OS matrix → users on v0.3.9 auto-update.

🤖 Generated with Claude Code

Summary by Sourcery

Centraliser le marqueur d’erreur « DB-ahead-of-binary » et rendre sa détection robuste face aux futurs changements dans l’empaquetage (wrapping) des erreurs.

Corrections de bugs :

  • Garantir que les échecs de pré-vérification « DB-ahead-of-binary » soient détectés de manière fiable en faisant correspondre un jeton de marqueur partagé plutôt qu’en s’appuyant sur un préfixe d’erreur codé en dur.

Améliorations :

  • Introduire une constante publique partagée DB_AHEAD_MARKER, utilisée à la fois par la couche base de données et par la logique de démarrage de l’application pour identifier les erreurs « DB-ahead-of-binary ».
  • Clarifier la documentation concernant l’emplacement d’écriture du fichier de notification STARTUP_BLOCKED par rapport à la base de données de l’application.

Tests :

  • Ajouter un test de régression qui vérifie que DB_AHEAD_MARKER peut être localisé et que sa charge utile peut être correctement extraite sous plusieurs schémas d’empaquetage d’erreurs.
Original summary in English

Summary by Sourcery

Centralize the DB-ahead-of-binary error marker and make its detection robust to future changes in error wrapping.

Bug Fixes:

  • Ensure DB-ahead-of-binary pre-flight failures are reliably detected by matching a shared marker token instead of relying on a hard-coded error prefix.

Enhancements:

  • Introduce a shared public DB_AHEAD_MARKER constant used by both the DB layer and app startup logic to identify DB-ahead-of-binary errors.
  • Clarify documentation around where the STARTUP_BLOCKED notice file is written relative to the application database.

Tests:

  • Add a regression test that verifies the DB_AHEAD_MARKER can be located and its payload extracted correctly under multiple error-wrapping patterns.

Sourcery flagged that `lib.rs::setup` was using
`e.strip_prefix("Failed to init SQLite: DB_AHEAD::")` — fragile
because any future change to the upstream wrapping in
`setup_result` would silently break the detection and the
STARTUP_BLOCKED.txt notice would never be written for the very
case the hardening was meant to catch.

Fix:
- Extract the marker as `pub const db::DB_AHEAD_MARKER`. Single
  source of truth on both sides — producer in `init_pool` and
  consumer in `lib.rs` reference the same constant.
- Consumer now uses `e.find(db::DB_AHEAD_MARKER)` instead of
  `strip_prefix("Failed to init SQLite: DB_AHEAD::")`. Robust to
  any wrapping; the marker contains `::` so false positives in
  plain-French error messages are not realistic.
- New `db_ahead_marker_is_findable_even_when_wrapped` test
  exercises 4 distinct wrappings (current, alternative, none,
  multi-layer) to lock the contract.

Also clarified the comment in lib.rs about path semantics: the
notice file lives in `dirs::data_dir().join("getpostcraft")`
NEXT TO `app.db`, not in the log dir (which uses the bundle
identifier `app.getpostcraft` on Windows — a Tauri/Windows
quirk).

Tests: Rust 205/205 (was 204/204), clippy + fmt clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented May 11, 2026

Copy link
Copy Markdown

Guide du réviseur

Centralise le marqueur DB_AHEAD dans une constante partagée, met à jour la gestion des erreurs côté producteur/consommateur pour l’utiliser via une recherche de sous-chaîne plutôt qu’un préfixe codé en dur, clarifie les commentaires sur la notification de blocage au démarrage, et ajoute un test de régression garantissant que le marqueur reste détectable sous divers schémas d’empaquetage d’erreurs.

Diagramme de séquence pour la production et la gestion de l’erreur DB_AHEAD_MARKER

sequenceDiagram
    actor User
    participant Run as lib_run
    participant DB as db_init_pool
    participant Checker as check_db_is_not_ahead_of_binary
    participant Notice as write_startup_blocked_notice

    User->>Run: run()
    Run->>DB: init_pool()
    DB->>Checker: check_db_is_not_ahead_of_binary(pool)
    Checker-->>DB: Err(e)
    DB-->>Run: Err(DB_AHEAD_MARKER + e)

    Run->>Run: find(db::DB_AHEAD_MARKER)
    alt marker_found
        Run->>Notice: write_startup_blocked_notice(payload)
        Run-->>User: Err(e)
    else marker_not_found
        Run-->>User: Err(e)
    end
Loading

Modifications par fichier

Changement Détails Fichiers
Centraliser le marqueur DB_AHEAD et mettre à jour la construction de l’erreur dans init_pool pour l’utiliser.
  • Introduire la constante publique DB_AHEAD_MARKER pour le jeton d’erreur « DB ahead ».
  • Mettre à jour init_pool pour préfixer la charge utile d’erreur avec DB_AHEAD_MARKER au lieu d’insérer directement la chaîne littérale.
  • Ajuster les commentaires de documentation environnants pour faire référence à DB_AHEAD_MARKER et clarifier le scénario utilisateur.
src-tauri/src/db/mod.rs
Rendre le consommateur dans lib.rs robuste face à l’empaquetage amont des erreurs en recherchant le marqueur partagé et en extrayant dynamiquement la charge utile.
  • Remplacer la détection basée sur strip_prefix par find(db::DB_AHEAD_MARKER) et découper la charge utile après l’index du marqueur.
  • Étendre et clarifier les commentaires expliquant le chemin du répertoire de données et la raison d’utiliser find plutôt que strip_prefix.
src-tauri/src/lib.rs
Ajouter un test de régression vérifiant que le marqueur DB_AHEAD reste détectable sous plusieurs schémas d’empaquetage.
  • Ajouter le test db_ahead_marker_is_findable_even_when_wrapped couvrant l’empaquetage actuel, des empaquetages futurs hypothétiques, l’absence d’empaquetage et l’empaquetage multi-couches.
  • Vérifier l’exactitude de l’extraction de la charge utile pour chaque empaquetage, afin de garantir que les modifications apportées à la logique d’empaquetage ne puissent pas casser silencieusement la gestion de STARTUP_BLOCKED.txt.
src-tauri/src/db/mod.rs

Conseils et commandes

Interagir avec Sourcery

  • Déclencher une nouvelle revue : Commentez @sourcery-ai review sur la pull request.
  • Poursuivre les discussions : Répondez directement aux commentaires de revue de Sourcery.
  • Générer une issue GitHub à partir d’un commentaire de revue : Demandez à Sourcery de créer une issue à partir d’un commentaire de revue en y répondant. Vous pouvez aussi répondre à un commentaire de revue avec @sourcery-ai issue pour créer une issue à partir de celui-ci.
  • Générer un titre de pull request : Écrivez @sourcery-ai n’importe où dans le titre de la pull request pour générer un titre à tout moment. Vous pouvez aussi commenter @sourcery-ai title sur la pull request pour (re)générer le titre à tout moment.
  • Générer un résumé de pull request : Écrivez @sourcery-ai summary n’importe où dans le corps de la pull request pour générer un résumé de PR exactement à l’endroit souhaité. Vous pouvez aussi commenter @sourcery-ai summary sur la pull request pour (re)générer le résumé à tout moment.
  • Générer un guide du réviseur : Commentez @sourcery-ai guide sur la pull request pour (re)générer le guide du réviseur à tout moment.
  • Résoudre tous les commentaires Sourcery : Commentez @sourcery-ai resolve sur la pull request pour résoudre tous les commentaires Sourcery. Utile si vous avez déjà traité tous les commentaires et ne souhaitez plus les voir.
  • Rejeter toutes les revues Sourcery : Commentez @sourcery-ai dismiss sur la pull request pour rejeter toutes les revues Sourcery existantes. Particulièrement utile si vous voulez repartir de zéro avec une nouvelle revue — n’oubliez pas de commenter @sourcery-ai review pour déclencher une nouvelle revue !

Personnaliser votre expérience

Accédez à votre tableau de bord pour :

  • Activer ou désactiver des fonctionnalités de revue telles que le résumé de pull request généré par Sourcery, le guide du réviseur, et d’autres.
  • Changer la langue de la revue.
  • Ajouter, supprimer ou modifier des instructions de revue personnalisées.
  • Ajuster d’autres paramètres de revue.

Obtenir de l’aide

Original review guide in English

Reviewer's Guide

Centralizes the DB_AHEAD marker into a shared constant, updates producer/consumer error handling to use it via substring search instead of a hard-coded prefix, clarifies startup-block notice comments, and adds a regression test ensuring the marker remains detectable under various error wrappings.

Sequence diagram for DB_AHEAD_MARKER error production and handling

sequenceDiagram
    actor User
    participant Run as lib_run
    participant DB as db_init_pool
    participant Checker as check_db_is_not_ahead_of_binary
    participant Notice as write_startup_blocked_notice

    User->>Run: run()
    Run->>DB: init_pool()
    DB->>Checker: check_db_is_not_ahead_of_binary(pool)
    Checker-->>DB: Err(e)
    DB-->>Run: Err(DB_AHEAD_MARKER + e)

    Run->>Run: find(db::DB_AHEAD_MARKER)
    alt marker_found
        Run->>Notice: write_startup_blocked_notice(payload)
        Run-->>User: Err(e)
    else marker_not_found
        Run-->>User: Err(e)
    end
Loading

File-Level Changes

Change Details Files
Centralize DB_AHEAD marker and update init_pool error construction to use it.
  • Introduce public constant DB_AHEAD_MARKER for the DB-ahead error token.
  • Update init_pool to prepend DB_AHEAD_MARKER to the error payload instead of inlining the string literal.
  • Adjust surrounding documentation comments to reference DB_AHEAD_MARKER and clarify user scenario.
src-tauri/src/db/mod.rs
Make lib.rs consumer robust to upstream error wrapping by searching for the shared marker and extracting the payload dynamically.
  • Replace strip_prefix-based detection with find(db::DB_AHEAD_MARKER) and slice the payload after the marker index.
  • Expand and clarify comments explaining the data directory path and rationale for using find over strip_prefix.
src-tauri/src/lib.rs
Add regression test asserting the DB_AHEAD marker remains discoverable under multiple wrapping patterns.
  • Add db_ahead_marker_is_findable_even_when_wrapped test covering current wrapping, hypothetical future wrappings, no wrapping, and multi-layer wrapping.
  • Verify payload extraction correctness for each wrapping, ensuring changes to wrapping logic cannot silently break STARTUP_BLOCKED.txt handling.
src-tauri/src/db/mod.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - j’ai laissé quelques retours d’ensemble :

  • Envisagez d’extraire la logique de find/découpage du payload dans un petit helper (par ex. db::extract_db_ahead_payload(&str) -> Option<&str>) afin que lib.rs et le test de régression partagent une seule implémentation pour localiser et retirer DB_AHEAD_MARKER.
Invite pour les agents IA
Veuillez traiter les commentaires de cette revue de code :

## Commentaires généraux
- Envisagez d’extraire la logique de `find`/découpage du payload dans un petit helper (par ex. `db::extract_db_ahead_payload(&str) -> Option<&str>`) afin que `lib.rs` et le test de régression partagent une seule implémentation pour localiser et retirer `DB_AHEAD_MARKER`.

Sourcery est gratuit pour l’open source — si vous aimez nos revues, pensez à les partager ✨
Aidez-moi à être plus utile ! Veuillez cliquer sur 👍 ou 👎 sur chaque commentaire et j’utiliserai ces retours pour améliorer vos revues.
Original comment in English

Hey - I've left some high level feedback:

  • Consider extracting the find/payload-slicing logic into a small helper (e.g. db::extract_db_ahead_payload(&str) -> Option<&str>) so both lib.rs and the regression test share a single implementation for locating and stripping DB_AHEAD_MARKER.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider extracting the `find`/payload-slicing logic into a small helper (e.g. `db::extract_db_ahead_payload(&str) -> Option<&str>`) so both `lib.rs` and the regression test share a single implementation for locating and stripping `DB_AHEAD_MARKER`.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@thierryvm thierryvm merged commit c61418a into main May 11, 2026
5 checks passed
@thierryvm thierryvm deleted the hotfix/v0.3.10-db-ahead-marker-robust branch May 11, 2026 18:51
thierryvm added a commit that referenced this pull request May 11, 2026
PR #65 follow-up. Sourcery flagged the find-and-slice for the
DB_AHEAD payload as duplicated logic between lib.rs and the
regression test. One implementation is better.

- New `pub fn extract_db_ahead_payload(err: &str) -> Option<&str>`
  in `db/mod.rs`. Returns `Some(payload)` when the marker is in
  the string, `None` otherwise. lib.rs and the test now both
  consume this helper.
- Negative-case test added: unrelated errors (sidecar timeout,
  out-of-disk-space, window builder errors, empty string) must
  return None — otherwise STARTUP_BLOCKED.txt would get written
  for unrelated failures and dilute its signal.

Tests: Rust 207/207 (was 205), clippy + fmt clean. Five
db_ahead* tests now cover the helper end-to-end:
- passes on fresh install
- passes when DB matches binary
- blocks when DB has future migration
- extracts even when wrapped
- returns None when marker absent

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant